package waal.pc.backend.module;


import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import waal.pc.backend.Utility;
import waal.pc.backend.channels.Channel;
import waal.pc.backend.channels.ChannelEvent;
import waal.pc.backend.channels.ChannelEventListener;
import waal.pc.backend.hub.Hub;

public abstract class Module {

	Hub hub;
	boolean initilized = false, active = false;
	boolean hasInput = false, hasOutput = false;
	
	boolean[] activeChannels, input;
	
	int bits, channelCount, moduleNumber, id, sendConfigCommand;
	long minTimeBase;
	String name, unit;
	double max, min;
	
	Set<ChannelEventListener> channelEventListener;
	Set<Channel> inChannelSet;
	Set<Channel> outChannelSet;
	Set<Channel> allChannelSet;
	
	public Module(Hub hub, int number, boolean active, String name, int configCommand) {
		this.hub = hub;
		this.moduleNumber = number;
		this.name = name;
		this.channelEventListener = new HashSet<ChannelEventListener>();
		this.fireModuleEvent(1);
		this.active = active;
		this.inChannelSet = new HashSet<Channel>();
		this.outChannelSet = new HashSet<Channel>();
		this.allChannelSet = new TreeSet<Channel>();
		this.sendConfigCommand = configCommand;
		this.id = ((hub.getNumber() * 100) + number)*10;
	}
	
	protected void initModule(boolean active, int channels, int bits, long minTimeBase, double min, double max, String unit) {
		this.active = active;
		this.bits = bits;
		this.min = min;
		this.max = max;
		this.bits = bits;
		this.minTimeBase = minTimeBase;
		this.unit = unit;
		this.channelCount = channels;
		
		this.activeChannels = new boolean[channels];
		this.input = new boolean[channels];
	}
	
	public abstract void processConfig(int[] data);
		
	public boolean hasInput() {
		return this.hasInput;
	}

	public boolean hasOutput() {
		return this.hasOutput;
	}
	
	public boolean isInitilized() {
		return this.initilized;
	}
	
	public int getBits() {
		return this.bits;
	}
	
	public Set<Channel> getChannels() {
		return this.allChannelSet;
	}
	
	public abstract Channel getChannel(int number);
	
	public int getChannelCount() {
		return this.channelCount;
	}
		
	public Hub getHub() {
		return this.hub;
	}
	
	public int getID() {
		return this.id;
	}

	public Set<Channel> getInputChannels() {
		return this.inChannelSet;
	}
	
	public double getMax() {
		return this.max;
	}
	
	public double getMin() {
		return this.min;
	}
	
	public long getMinimalTimeBase() {
		return this.minTimeBase;
	}

	public Set<Channel> getOutputChannels() {
		return this.outChannelSet;
	}

	public String getName() {
		return this.name;
	}
	
	public int getNumber() {
		return this.moduleNumber;
	}
	
	public String getUnit() {
		return this.unit;
	}
	
	public boolean isActive() {
		return this.active;
	}
	
	public boolean isChannelActive(int number) {
		if(number >= 0 && number < this.channelCount) {
			return this.activeChannels[number];
		}
		return false;
	}
	
	public abstract boolean isDigital();
	
	public abstract void sendChannelActive(int ch, boolean value);
	
	public abstract void setChannelName( int ch, String name); 
	
	public void setModuleName(String name) {
		this.name = name;
	}
			
	public void setModuleActice(boolean active) {
		if(this.active != active) {
			this.active = active;
			this.fireModuleEvent(3);
		}
	}
	 
	public String toString() {
		return this.name;
	}
	
	public void removeModule() {
		//TODO
		this.fireModuleEvent(2);
	}
	
	void fireModuleEvent( int eventNumber) {
		this.hub.fireModuleEvent(new ModuleEvent(eventNumber, this));
	}
	
	public boolean addChannelEventListener(ChannelEventListener listener) {
		return this.channelEventListener.add(listener);
	}
	
	public boolean removeChannelEventListener(ChannelEventListener listener) {
		return this.channelEventListener.remove(listener);
	}
	
	public void fireChannelEvent(ChannelEvent e) {
		//System.out.println("Fire Channel Event " + e.getEvent() + " for channel: " + e.getChannel().getChannelNumber() + "@Hub:" + this.hub.getNumber() + "-Mod: " + this.number + " Event: " + e.getEventText());
		for(Iterator<ChannelEventListener> i = this.channelEventListener.iterator(); i.hasNext(); ) {
			i.next().actionChannelEvent(e);
		}
	}	

	public void SendConfig(int channel, int command) {
		int[] data = new int[4];
		data[0] = this.sendConfigCommand;
		data[1] = this.moduleNumber;
		data[2] = channel+1;
		data[3] = command;
		this.hub.sendModuleConfig(Utility.intAToByteAcs(data));
		
	}
	
	public void SendConfig(int channel, int command, int value) {
		int[] data = new int[5];
		data[0] = this.sendConfigCommand;
		data[1] = this.moduleNumber;
		data[2] = channel+1;
		data[3] = command;
		data[4] = value;
		this.hub.sendModuleConfig(Utility.intAToByteAcs(data));
	}
	
	public void SendConfig(int channel, int command, int value[]) {
		int[] data = new int[4+value.length];
		data[0] = this.sendConfigCommand;
		data[1] = this.moduleNumber;
		data[2] = channel+1;
		data[3] = command;
		for(int i = 0; i < value.length; i++) {
			data[4+i] = value[i];
		}
		this.hub.sendModuleConfig(Utility.intAToByteAcs(data));
	}

	public abstract void  updateValues();
	
}


 
 
 
 
 
 
 

